package org.shaka.db.sqlbuilder.sql;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.shaka.db.sqlbuilder.component.Column;
import org.shaka.db.sqlbuilder.component.CriteriaFace;

import com.google.common.collect.Lists;

public class SqlColumn implements CriteriaFace {
    private String as;
    private Column column;

    public SqlColumn(Column column, String as) {
        this.column = column;
        this.as = as;
    }

    public String getAs() {
        return as;
    }

    public String selectColumnPartial() {
        return String.format("%s.%s AS %s", as, column.name(),
                StringUtils.join(new String[] { as.toUpperCase(), column.name().toUpperCase() }, "_"));
    }

    public String columnPartial() {
        return String.format("%s.%s", as, column.name());
    }

    public String valuePartial() {
        return String.format("%s.%s", as, column.name());
    }

    public String orderPartial() {
        return String.format("%s.%s", as, column.name());
    }

    @Override
    public SqlCondition isNull() {
        return new SqlCondition() {
            @Override
            public String conditionsPartial() {
                return String.format("%s IS NULL", columnPartial());
            }
        };
    }

    @Override
    public SqlCondition isNotNull() {
        return new SqlCondition() {
            @Override
            public String conditionsPartial() {
                return String.format("%s IS NOT NULL", columnPartial());
            }
        };
    }

    @Override
    public SqlCondition like(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s LIKE %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition notLike(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s NOT LIKE %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition equalTo(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s = %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition notEqualTo(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s <> %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition less(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s < %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition lessThen(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s <= %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition greater(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s > %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition greaterThen(Object value) {
        return new SqlCondition(value) {
            @Override
            public String conditionsPartial() {
                return String.format("%s >= %s", columnPartial(), getFirstValue().getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition between(Object value1, Object value2) {
        return new SqlCondition(value1, value2) {
            @Override
            public String conditionsPartial() {
                return String.format("%s BETWEEN %s AND %s", columnPartial(), getValue(0).getConditionWord(),
                        getValue(1).getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition notBetween(Object value1, Object value2) {
        return new SqlCondition(value1, value2) {
            @Override
            public String conditionsPartial() {
                return String.format("%s NOT BETWEEN %s AND %s", columnPartial(), getValue(0).getConditionWord(),
                        getValue(1).getConditionWord());
            }
        };
    }

    @Override
    public SqlCondition in(Object... values) {
        return new SqlCondition(values) {
            @Override
            public String conditionsPartial() {
                List<String> conditionWords = Lists.newArrayList();
                for (Value value : getValues()) {
                    conditionWords.add(value.getConditionWord());
                }
                return String.format("%s IN (%s)", columnPartial(), StringUtils.join(conditionWords, ", "));
            }
        };
    }

    @Override
    public SqlCondition notIn(Object... values) {
        return new SqlCondition(values) {
            @Override
            public String conditionsPartial() {
                List<String> conditionWords = Lists.newArrayList();
                for (Value value : getValues()) {
                    conditionWords.add(value.getConditionWord());
                }
                return String.format("%s NOT IN (%s)", columnPartial(), StringUtils.join(conditionWords, ", "));
            }
        };
    }
}
